/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFVDC
  \brief virtual class for DCs in general - just for abstraction
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-11-01
  \date 2021-11-30 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-11-01   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFVDC_h
#define ETFVDC_h

#include <vector>
#include "ETFDetector.h"
#include "TrackType.h"

using std::vector;

class TClonesArray;
class TH1F;
class ETFHPTDCCh;
class ETFVTrack;
class ETFDCHit;

class ETFVDC : public ETFDetector{
public:
  ETFVDC(){}
  ETFVDC(const char *name);
  virtual ~ETFVDC();

  /// r = r(t); drift distance - drift time relation
  virtual double SpaceTimeRelation(double t);
  /// \param chId0: starting channel id for an ordered numbered set of wires
  virtual void FillChIdMap(int chId0) = 0; ///< fill the (channel id <-> uid) map
  /// identify ch and assign its identify
  virtual void Assign(const ETFRawChannel *ch, unsigned uid) override;
  virtual void PostAssign() override; ///< finish the processing of all the assigned data
  /// set the wire's projection to its normal plane
  virtual void SetHitProjection(ETFDCHit *h, DCType typeDC) = 0;
  void SetDCId(int id){ fDCId = id; }
  /// \retval false: if obtained drift time out of range
  /// NOTE that if trk has non-FitStatus::kUNFITTED FitStatus, this method
  /// would do nothing, as drift distance only changes with drift time,
  /// whose changes would ensure fFitStatus be set to FitStatus::kUNFITTED
  virtual bool SetDriftDistance(ETFVTrack *trk);
  virtual bool SetDriftDistance(ETFDCHit *h);

  // only 1 wire of adjacent wires is supposed to be fired: this method filter the others
  // it is now found that for the genuine hit the tl is earlier and tot is much larger
  // compared with the secondary spurious hits
  virtual void Filter(TClonesArray *c);
  virtual void Filter(){} // filter all layers

  /// get the fired sense wire layer
  /// \param type: XUV or XY; x12: X1 or X2
  virtual TClonesArray *GetHitsArray(DCType type, int x12) = 0;
  virtual int Multi(DCType type, int x12); // \return multiplicity of the wire layer
  virtual void ConstructGraph() override; ///< add sigle wires to fGDumb
  int GetDCId() const{ return fDCId; }
  int GetNL() const{ return fNL; }

  // ClassDef(ETFVDC, 0);

protected:
  /// \param wireId: ->X1->X2 (0->(fNL-1)->fNL-(2*fNL-1)), along x increasing direction
  /// \param typeDC: 0-1-2: X-U-V or X-Y--
  virtual void AddHit(const ETFRawChannel *ch, int wireId, DCType typeDC) = 0;
  virtual unsigned uid(unsigned int typeDC, int x12, int wireId); ///< generate uid
  /// initial space-time relation (STR) using parabola passing (0,0), (rm,tm)
  static double ParaSTR(double rm, double tm, double t);

  int fDCId; ///< drift chamber id: along beam direction
  unsigned type[3]; ///< typeDC, X1-2, senseWireId, or user-defined

  ///--- DC specifications ---///
  int fNL; ///< number of signal wires per layer
  double fSenseWireDistance; ///< distance between two adjacent sense wires
  double fMaxDL; ///< maximum drift distance = fSenseWireDistance/2.
  double fLayerSpace12; ///< distance between X1-X2 or Y1-Y2(U,V) (should be the same)
  double fLayerSpaceXY; ///< distance between X1-Y1 or X2-Y2(U,V) (should be the same)
  /// in (z->beam,y->up, right-hand) frame
  double fStagger12; ///< staggering of X2 w.r.t. X1 (or Y1->Y2 (U,V), should be the same)
  double fStaggerY12; ///< in case that X and Y wires have different values
  /// the min x0 of the leftmost (or rightmost) X1 sense wire (detector local frame)
  double fX0Min; ///< the same applies to Y (or U, V) wires
  double fY0Min; ///< in case that X and Y wires have different values

  ///-- experiment specific configurations ---///
  double fDTLB, fDTHB; ///< [drift time low bound, drfit time high bound]
  vector<double> fvstr; ///< parameter of polynomial STR read from user YAML file
  /// the histo that is from integration of drift time distribution
  const TH1F *fhrt; //! ///< which directly provides R(t)
};

#endif
